package br.com.recipe.dao;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import br.com.recipe.exception.RecipeException;

public class HibernateHelper {
	
	private static SessionFactory sessionFactory;
	
    public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public static void setSessionFactory(SessionFactory sessionFactory) {
		HibernateHelper.sessionFactory = sessionFactory;
	}

	/**
     * Exec a query (hql) and return the result (list)
     * @param hql
     * @return List
     * @throws LeadException 
     */
    public static List<?> execQuery(String hql) throws RecipeException {
        return execQuery(hql, null);        
    }
    
    /**
     * Exec a query (hql/params) and return the result (list)
     * @param <V>
     * @param hql
     * @param params
     * @return List
     * @throws LeadException 
     */
    public static <V> List<?> execQuery(String hql, Map<?,?> params) throws RecipeException {
        Session session = null;
        Transaction tx = null;
        Query query = null;
        List<?> retorno = null; 
                
        try {
            session = HibernateSessionFactory.getUnManagedSession();
            tx = session.beginTransaction();
            query = session.createQuery(hql);            
            if((params != null) && (params.size() > 0)){
                Iterator<?> itParamNames = params.keySet().iterator();
                
                while(itParamNames.hasNext()){
                    String paramName = (String) itParamNames.next();
                    Object value = params.get(paramName);
                    
                    query.setParameter(paramName, value);
                }
            }            
            retorno = query.list();
            tx.commit();
        } catch (HibernateException hbe) {
            if(tx != null) {
                tx.rollback();
            }
            throw new RecipeException(hbe);
        } finally {
            if(session != null) {
                session.close();
            }
        }        
        return retorno;        
    }
    
    /**
     * Save or update a object
     * @param o
     * @throws LeadException 
     */
    public static void save(Object o)throws RecipeException {
        Session session = null;
        Transaction tx = null;
        
        try {
            session = HibernateSessionFactory.getUnManagedSession();
            tx = session.beginTransaction();
            session.saveOrUpdate(o);
            tx.commit();
        } catch (HibernateException hbe) {
            if(tx != null) {
                tx.rollback();
            }
            throw new RecipeException(hbe);
        } finally {
            if(session != null) {
                session.close();
            }
        }
    }
    
    /**
     * Get an object by Id
     * @param c
     * @param id
     * @return Objjet
     * @throws LeadException 
     */
    public static Object getById(Class<?> c, Serializable id)throws RecipeException {
        Session session = null;
        Transaction tx = null;
        Object retorno = null;        
        
        try {
            session = HibernateSessionFactory.getUnManagedSession();
            tx = session.beginTransaction();
            Object obj = session.get(c, id);      
            tx.commit();
            retorno = obj;
        } catch (HibernateException hbe) {
            if(tx != null) {
                tx.rollback();
            }
            throw new RecipeException(hbe);
        } finally {
            if(session != null) {
                session.close();
            }
        }
        return retorno;        
    }
    
    /**
     * Save a object
     * @param o
     * @throws LeadException 
     */
    public static void delete(Object o)throws RecipeException {
        Session session = null;
        Transaction tx = null;
        
        try {
            session = HibernateSessionFactory.getUnManagedSession();
            tx = session.beginTransaction();
            session.delete(o);
            tx.commit();
        } catch (HibernateException hbe) {
            if(tx != null) {
                tx.rollback();
            }
            throw new RecipeException(hbe);
        } finally {
            if(session != null) {
                session.close();
            }
        }
    }
	
}
